package util

import (
	"bytes"
	"encoding/json"
	"fmt"
	"likeadmin/model/client"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// OceanengineCallbackUtil 头条回传工具类
type OceanengineCallbackUtil struct{}

// AdCallback 广告回调参数结构体
type AdCallback struct {
	Action          string `json:"action"`
	MicroCreateTime int64  `json:"micro_create_time"`
	CallbackURL     string `json:"callback_url"`
	Money           uint   `json:"money"`
}

// conversionRequest 转化回传请求结构体
type conversionRequest struct {
	EventType string `json:"event_type"`
	Timestamp int64  `json:"timestamp"`
	Context   struct {
		Ad struct {
			Callback string `json:"callback"`
		} `json:"ad"`
	} `json:"context"`
	Properties struct {
		PayAmount uint `json:"pay_amount"`
	} `json:"properties"`
}

// Callback 转化回传主方法
func (o OceanengineCallbackUtil) Callback(adCallback *AdCallback) (string, error) {

	// 确定事件类型
	eventType, err := o.getEventType(adCallback.Action)
	if err != nil {
		return fmt.Sprintf("头条回调处理解析回调URL中: Action=%v::error", adCallback.Action), err
	}

	// 解析回调URL中的参数
	callbackParam, err := o.parseCallbackURL(adCallback.CallbackURL)
	if err != nil {
		return fmt.Sprintf("头条回调处理解析回调URL中: CallbackURL=%v::error", err), err
	}

	// 构造回传数据
	conversionReq := &conversionRequest{
		EventType: eventType,
		Timestamp: adCallback.MicroCreateTime,
	}
	conversionReq.Context.Ad.Callback = callbackParam

	// 设置付费金额（如果是付费事件）
	if eventType == "active_pay" {
		conversionReq.Properties.PayAmount = adCallback.Money
	}
	log.Printf("头条回调: conversionReq=%+v", conversionReq)
	// 发送回传请求
	resultData, err := o.httpPost("https://analytics.oceanengine.com/api/v2/conversion", conversionReq)
	if retCode, ok := resultData["code"].(float64); ok && retCode == 0 {
		log.Printf("头条回调处理成功: result=%+v", resultData)
		return fmt.Sprintf("头条回调处理成功: id=%v::success", resultData), nil
	} else {
		log.Printf("头条回调处理失败: result=%+v", resultData)
		return fmt.Sprintf("头条回调处理失败: id=%v::error", err), err
	}

}

// getEventType 根据action获取事件类型
func (o OceanengineCallbackUtil) getEventType(action string) (string, error) {
	switch action {
	case "PAY":
		return "active_pay", nil // 付费
	case "ADD_SCREEN":
		return "game_addiction", nil // 关键行为
	case "ACTIVATION":
		return "active", nil // 激活
	case "REGISTER":
		return "active_register", nil // 注册
	default:
		return "", fmt.Errorf("巨量引擎回传数据不存在对应的回传类型")
	}
}

// parseCallbackURL 解析回调URL中的callback参数
func (o OceanengineCallbackUtil) parseCallbackURL(callbackURL string) (string, error) {
	u, err := url.Parse(callbackURL)
	if err != nil {
		return "", err
	}

	params, err := url.ParseQuery(u.RawQuery)
	if err != nil {
		return "", err
	}

	callback := params.Get("callback")
	if callback == "" {
		return "", fmt.Errorf("callback参数不存在")
	}

	return callback, nil
}

// httpPost 发送HTTP POST请求
func (o OceanengineCallbackUtil) httpPost(url string, data *conversionRequest) (map[string]interface{}, error) {
	// 这里需要实现实际的HTTP请求逻辑
	// 示例代码：
	jsonData, _ := json.Marshal(data)
	resp, err := http.Post(url, "application/json", strings.NewReader(string(jsonData)))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result map[string]interface{}
	json.NewDecoder(resp.Body).Decode(&result)
	return result, nil
}

const UrlPrefix = "https://ad.oceanengine.com/open_api"

// GetAccessToken 头条获取授权token
func (o OceanengineCallbackUtil) GetAccessToken(authCode, clientID, secret string) (map[string]interface{}, error) {

	data := map[string]string{
		"app_id":     clientID,
		"secret":     secret,
		"grant_type": "auth_code",
		"auth_code":  authCode,
	}

	jsonData, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}

	// 使用bytes.NewReader避免不必要的字符串转换
	resp, err := http.Post(UrlPrefix+"/oauth2/access_token/", "application/json", bytes.NewReader(jsonData))
	if err != nil {
		return nil, err
	}
	defer func() {
		if closeErr := resp.Body.Close(); closeErr != nil {
			// 记录关闭错误但不影响主流程
			fmt.Printf("Failed to close response body: %v\n", closeErr)
		}
	}()

	// 检查HTTP响应状态码
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("HTTP request failed with status code: %d", resp.StatusCode)
	}

	var result map[string]interface{}

	// 处理JSON解码错误
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("failed to decode JSON response: %w", err)
	}

	return result, nil
}

// AccesstokenRefresh
func (o OceanengineCallbackUtil) AccesstokenRefresh(refreshToken, clientID, secret string) (map[string]interface{}, error) {

	data := map[string]string{
		"app_id":        clientID,
		"secret":        secret,
		"grant_type":    "refresh_token",
		"refresh_token": refreshToken,
	}

	jsonData, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}

	// 使用bytes.NewReader避免不必要的字符串转换
	resp, err := http.Post(UrlPrefix+"/oauth2/refresh_token/", "application/json", bytes.NewReader(jsonData))
	if err != nil {
		return nil, err
	}
	defer func() {
		if closeErr := resp.Body.Close(); closeErr != nil {
			// 记录关闭错误但不影响主流程
			fmt.Printf("Failed to close response body: %v\n", closeErr)
		}
	}()

	// 检查HTTP响应状态码
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return nil, fmt.Errorf("HTTP request failed with status code: %d", resp.StatusCode)
	}

	var result map[string]interface{}

	fmt.Printf("HTTP Body: %v", resp.Body)
	// 处理JSON解码错误
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("failed to decode JSON response: %w", err)
	}

	return result, nil
}

func (o OceanengineCallbackUtil) AdDataOcean(account client.Account, today string) (cost uint, e error) {

	// 解析日期字符串
	parsedTime, err := time.Parse("20060102", today)
	if err != nil {
		e = fmt.Errorf("每日报表统计-日期解析错误:%v", err)
		return
	}

	// 格式化为目标格式
	formattedDate := parsedTime.Format("2006-01-02")

	// 调用广告报告接口
	res, err := o.adReport(account.AccountNumber, account.AccessToken, formattedDate)

	fmt.Print(fmt.Sprintf("巨量成本拉取成功：%s, 返回信息: %v 错误信息%v", account.AccountNumber, res, err))

	if err != nil {
		return 0, err
	}

	// 安全地提取total_metrics下的stat_cost
	if res == nil {
		return 0, fmt.Errorf("API响应为空")
	}

	// 检查data字段
	data, ok := res["data"].(map[string]interface{})
	if !ok {
		return 0, fmt.Errorf("无效的data格式")
	}

	// 检查total_metrics字段
	totalMetrics, ok := data["total_metrics"].(map[string]interface{})
	if !ok {
		return 0, fmt.Errorf("无效的total_metrics格式")
	}

	// 检查stat_cost字段并转换
	statCost, ok := totalMetrics["stat_cost"]
	if !ok {
		return 0, fmt.Errorf("stat_cost字段不存在")
	}

	// 根据实际类型进行转换
	var costValue float64
	switch v := statCost.(type) {
	case float64:
		costValue = v
	case int:
		costValue = float64(v)
	case uint:
		costValue = float64(v)
	case string:
		parsedValue, err := strconv.ParseFloat(v, 64)
		if err != nil {
			return 0, fmt.Errorf("无法将字符串转换为float64: %v", err)
		}
		costValue = parsedValue
	default:
		return 0, fmt.Errorf("不支持的stat_cost类型: %T", v)
	}

	// 确保转换为正数
	if costValue < 0 {
		costValue = 0
	}

	return uint(costValue * 100), nil
}

const adUrlPrefix = "https://api.oceanengine.com"

// adReport 广告报告接口
func (o OceanengineCallbackUtil) adReport(accountNumber, accessToken, date string) (map[string]interface{}, error) {

	urlLink := adUrlPrefix + "/open_api/v3.0/report/custom/get/"

	// 如果日期为空，使用当前日期
	if date == "" {
		date = time.Now().Format("2006-01-02")
	}

	// 构造请求数据
	dimensions := []string{"stat_time_day", "cdp_promotion_name", "cdp_promotion_id", "external_action", "ad_platform_cdp_promotion_bid"}
	metrics := []string{"stat_cost", "show_cnt", "cpm_platform", "click_cnt", "ctr", "cpc_platform", "convert_cnt", "conversion_cost", "conversion_rate", "deep_convert_cnt", "deep_convert_cost", "deep_convert_rate"}

	dimensionsJSON, err := json.Marshal(dimensions)
	if err != nil {
		return nil, fmt.Errorf("序列化dimensions失败: %v", err)
	}

	metricsJSON, err := json.Marshal(metrics)
	if err != nil {
		return nil, fmt.Errorf("序列化metrics失败: %v", err)
	}

	filtersJSON, _ := json.Marshal([]interface{}{})
	orderByJSON, _ := json.Marshal([]interface{}{})

	// 构造查询参数
	params := url.Values{}
	params.Add("advertiser_id", accountNumber)
	params.Add("dimensions", string(dimensionsJSON))
	params.Add("metrics", string(metricsJSON))
	params.Add("filters", string(filtersJSON))
	params.Add("start_time", date+" 00:00:00")
	params.Add("end_time", date+" 23:59:59")
	params.Add("order_by", string(orderByJSON))
	params.Add("page", "1")
	params.Add("page_size", "100")

	// 构造完整URL
	fullURL := urlLink + "?" + params.Encode()

	// 创建HTTP请求
	req, err := http.NewRequest("GET", fullURL, nil)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}

	// 添加请求头
	req.Header.Set("Access-Token", accessToken)

	// 发送请求
	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("发送请求失败: %v", err)
	}

	defer resp.Body.Close()
	//body, _ := ioutil.ReadAll(resp.Body)
	//fmt.Println(fmt.Sprintf("巨量成本拉取成功：%s, 响应信息: %v 错误信息%v", accountNumber, string(body), err))
	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP请求失败，状态码: %d", resp.StatusCode)
	}

	// 解析响应
	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	// 检查结果
	if result == nil {
		return nil, fmt.Errorf("API响应为空")
	}

	return result, nil
}
